/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package preka.clustering;

import java.util.ArrayList;
import java.util.Iterator;
import prefuse.Visualization;
import prefuse.visual.VisualItem;
import preka.IVC;
import preka.prefuse.visual.VisualInstance;
import preka.prefuse.visual.VisualInstances;
import weka.core.Instances;

/**
 *
 * @author vhbarros
 */
public class NoClustering {

    private static int NOT_FOUND        = -9999;
    private static String STR_NOT_FOUND = "";

    private Visualization m_vis;
    private VisualInstances m_visualInstances;
    private Instances m_data;
    private int [] m_clusterMapping;
    private String [] m_clusterNameMapping;
    private int [] m_clusterAssignments;

    public NoClustering () {

    }
    
    public NoClustering(Visualization vis, VisualInstances visualInstances, Instances data) {
        m_vis                   = vis;
        m_visualInstances       = visualInstances;
        m_data                  = data;
        m_clusterMapping        = new int[m_data.numClasses()];
        m_clusterNameMapping    = new String[m_data.numClasses()];
        m_clusterAssignments    = new int[m_data.numInstances()];
    }

    private String getClusterName(int visualCluster) {
        for(int i=0; i<m_data.numClasses(); i++)
            if(m_clusterMapping[i] == visualCluster)
                return m_clusterNameMapping[i];

        return STR_NOT_FOUND;
    }

    private int getClosestCenterInstance(double x, double y) {
        VisualItem vi;
        double dist, minDist = Double.MAX_VALUE;
        int closestCenter = NOT_FOUND;
        
        for (int i=-1 ; i>=m_data.numClasses()*-1; i--) {
            vi = m_visualInstances.getVisualItem(m_vis, IVC.NODES_GROUP, i);
            dist = IVC.distance(x, y, vi.getX(), vi.getY());
            if (minDist > dist) {
                minDist = dist;
                closestCenter = i;
            }
        }
        
        return closestCenter;
    }
    
    private int getVisualCluster(String className) {
        VisualInstance vinst;
        VisualItem vi;
        ArrayList vinsts = m_visualInstances.getMovedVisualInstances();
        Iterator moved = vinsts.iterator();
        while (moved.hasNext()) {
            vinst = (VisualInstance) moved.next();
            if (vinst.getClassName().equals(className)) {
                vi = m_visualInstances.getVisualItem(m_vis, IVC.NODES_GROUP, vinst.getNumInstance());
                return getClosestCenterInstance(vi.getX(), vi.getY());
            }
        }
        return NOT_FOUND;
    }
    
    private void mapVisualClusters() {
        int visualCluster;
        boolean exists, mapped = true;
        
        for (int i=0 ; i<m_data.numClasses(); i++) {
            m_clusterNameMapping[i] = m_data.classAttribute().value(i);
            visualCluster = getVisualCluster(m_clusterNameMapping[i]);
            m_clusterMapping[i] = visualCluster;
            if (visualCluster == NOT_FOUND)
                mapped = false;

        }

        if (!mapped)
            for (int i=-1 ; i>=m_data.numClasses()*-1; i--) {
                exists = false;
                for (int j=0 ; j<m_data.numClasses(); j++) {
                    if(m_clusterMapping[j] == i)
                        exists = true;
                }
                if (!exists)
                    for (int j=0 ; j<m_data.numClasses(); j++)
                        if(m_clusterMapping[j] == NOT_FOUND)
                            m_clusterMapping[j] = i;
            }
    }

    // TODO: Assume que os primeiros movimentos forma grupos diferentes. Alterar!
    public boolean setInitialCenters() {
        
        ArrayList moved = m_visualInstances.getMovedVisualItems(m_vis, IVC.NODES_GROUP);
        if (moved.size() > m_data.numClasses())
            return false;
            
        int tmpNumMovedItems = moved.size();
        int visualCluster;
        VisualItem vi, vi2;
        
        while (tmpNumMovedItems != 0){
            visualCluster = tmpNumMovedItems*-1;
            vi = m_visualInstances.getVisualItem(m_vis, IVC.NODES_GROUP, visualCluster);
            vi2 = (VisualItem) moved.get(tmpNumMovedItems-1);
            vi.setX(vi2.getX());
            vi.setY(vi2.getY());
            vi.setEndX(vi2.getX());
            vi.setEndY(vi2.getY());
            tmpNumMovedItems--;
        }

        return true;
    }
    
    public void buildClusterer () {
        VisualItem vi;
        int i=0;

        mapVisualClusters();
        
        Iterator items = m_vis.items(IVC.NODES_GROUP);
        while(items.hasNext()) {
            vi = (VisualItem) items.next();
            if (vi.getInt(IVC.INSTANCE_ATTRIBUTE) >= 0) {
                m_clusterAssignments[i] = getClosestCenterInstance(vi.getX(), vi.getY());
                i++;
            }
        }
    }

    public int [] getClusterAssignments () {
        return m_clusterAssignments;
    }

    public double randIndex() {
        VisualInstance vi;
        double numCorrect = 0, numInstances = m_data.numInstances();
        
        ArrayList vis = m_visualInstances.getVisualInstances();
        Iterator items = vis.iterator();
        while (items.hasNext()) {
            vi = (VisualInstance) items.next();
            if (vi.getClassName().equals(getClusterName(vi.getVisualCluster())))
                numCorrect++;
        }

        double RandIndex = /*100 **/ numCorrect
                        / (numInstances * (numInstances - 1) / 2);
        System.out.println("NumCorrect:"+numCorrect+" NumInstances:"+numInstances+" RandIndex:"+RandIndex);
        return RandIndex;
    }



}
